from typing import TYPE_CHECKING, Optional, List

from sqlmodel import Field, Relationship, SQLModel

from app.schemas.base_schema import MenuEnum
from .base import SQLBaseModel, IdType
from .role_menu import RoleMenu

if TYPE_CHECKING:
    from .role import Role


class BaseMenu(SQLModel):
    name: str = Field(index=True, description="名称")

    title: str = Field(index=True, description="标题")
    sort: int = Field(default=100, index=True, description="排序")

    auth_key: Optional[str] = Field(default=None, index=True, description="权限字符")

    path: Optional[str] = Field(description="路由地址")
    component_path: Optional[str] = Field(description="组件位置")
    redirect: Optional[str] = Field(default=None, description="重定向地址")
    icon: Optional[str] = Field(default=None, description="图标")
    type: Optional[MenuEnum] = Field(default=None, index=True, description="菜单类型")
    description: Optional[str] = Field(default=None, description="描述")

    is_hidden: bool = Field(default=False, description="是否在菜单栏显示")
    is_keepalive: bool = Field(default=False, description="是否缓存")
    is_affix: bool = Field(default=False, description="是否固定在标签页")
    is_enabled: bool = Field(default=True, index=True, description="是否启用")


class Menu(SQLBaseModel, BaseMenu, table=True):
    __tablename__ = "menu"

    """一对多自引用关系"""
    parent_id: Optional[IdType] = Field(
        default=None, index=True, foreign_key="menu.id", description="上级ID"
    )
    # 系统使用假删除，所有不需要级联删除，后续自己处理删除逻辑
    """
    选项	描述
        save-update	自动将新对象添加到会话中
        merge	级联合并操作
        expunge	级联清除操作
        delete	级联删除操作
        delete-orphan	删除不再与父对象关联的子对象
        all	等同于 save-update, merge, expunge, delete
        none	禁用所有级联
    """
    children: List["Menu"] = Relationship(
        back_populates="parent",
        sa_relationship_kwargs={"cascade": "save-update, merge","lazy": "raise"}
    )
    # 对于自引用关系，需要使用 sa_relationship_kwargs={"remote_side": [id]} 来指定关系的"远程端"
    parent: Optional["Menu"] = Relationship(
        back_populates="children", sa_relationship_kwargs={"remote_side": "Menu.id"}
    )

    """多对多关系"""
    roles: List["Role"] = Relationship(back_populates="menus", link_model=RoleMenu)
